import React from 'react';
import ReactDOM from 'react-dom';
import './index.css' ;


function Square(props) {
    // constructor(props) {
    //     super(props);
    //     this.state = {
    //         value: null,
    //     };
    // }


    return (
        <button className="square" onClick={
            props.onClick}>
            {props.value}
        </button>
    );

}


class Board extends React.Component {


    renderSquare(i) {
        return <Square
            value={this.props.squares[i]}
            onClick={() => this.props.onClick(i)}
        />;
    }


    render() {

        return (
            <div>
                <div className="board-row">
                    {this.renderSquare(0)}
                    {this.renderSquare(1)}
                    {this.renderSquare(2)}
                </div>
                <div className="board-row">
                    {this.renderSquare(3)}
                    {this.renderSquare(4)}
                    {this.renderSquare(5)}
                </div>
                <div className="board-row">
                    {this.renderSquare(6)}
                    {this.renderSquare(7)}
                    {this.renderSquare(8)}
                </div>
            </div>
        );
    }
}

function calculateWinner(squares) {
    const lines = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
        const [a, b, c] = lines[i];
        if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
            return squares[a];
        }
    }
    return null;

}

class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            history: [{
                squares: Array(9).fill(null),
            }],
            stepNumber: 0,
            xIsNext: true,
        };
    }

    handleClick(i) {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = history[history.length - 1];
        const squares = current.squares.slice();
        if (calculateWinner(squares) || squares[i]) {
            return;
        }
        squares[i] = this.state.xIsNext ? 'X' : 'O';
        this.setState({
            history: history.concat([{
                squares: squares,
            }]),
            stepNumber: history.length,
            xIsNext: !this.state.xIsNext
        });
    }

    jumpTo(step) {
        this.setState({
            stepNumber: step,
            xIsNext: (step % 2) === 0,
        });
    }

    render() {
        const history = this.state.history;
        const current = history[this.state.stepNumber];
        const winner = calculateWinner(current.squares);
        const moves = history.map((step, move) => {
            const desc = move ?
                'Go to move #' + move :
                'Go to game start';
            return (
                <li key={move}>
                    <button onClick={() => this.jumpTo(move)}>{desc}</button>
                </li>
            );
        });

        let status;
        if (winner) {
            status = 'Winner: ' + winner;
        } else {
            status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
        }
        return (
            <div className="game">
                <div className="game-board">
                    <Board
                        squares={current.squares}
                        onClick={(i) => this.handleClick(i)}
                    />
                </div>
                <div className="game-info">
                    <div>{status}</div>
                    <ol>{moves}</ol>
                </div>
            </div>
        );
    }
}

// ========================================
//变量声明
const name = "linzx";
//变量引用
const element = <h1>hello {name}</h1>;

//函数
function formatName(user) {
    return user.firstName + " " + user.lastName;
}

//对象
const user = {
    firstName: 'lin',
    lastName: "zongxiang",
};
//对象使用
const element2 = <h1>hello {formatName(user)}</h1>

//条件判断
function getGreeting(user) {
    if (user) {
        return <h1>hello {formatName(user)}</h1>
    } else {
        return <h1>hello Stranger</h1>
    }
}

//绑定属性
const element3 = <div tabIndex="0"></div>;
//属性绑定图片图片
const imageUrl = "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3807427310,283445384&fm=26&gp=0.jpg"
const element4 = <img src={imageUrl}></img>;

//包含很多子元素
const element5 = (
    <div>
        <h1>Hello!</h1>
        <h2>Good to see you here.</h2>
    </div>
);

//防止注入
const response = {
    potentiallyMaliciousInput: 'input',
};

const title = response.potentiallyMaliciousInput;
// 直接使用是安全的：
const element6 = <h1>{title}</h1>;

//表示对象
const element7 = (
    <h1 className="greeting">Hello,world!</h1>
);
//等同于如下
const element8 = React.createElement(
    'h1',
    {className: 'greeting'},
    'Hello, world!'
);
//相当如下伪对象
const element9 = {
    type: 'h1',
    props: {
        className: 'greeting',
        children: 'Hello, world!'
    }
};

//更新已渲染的元素
function tick() {
    const element = (
        <div>
            <h1>Hello,world</h1>
            <h2>It is {new Date().toLocaleTimeString()}</h2>
        </div>
    );

    ReactDOM.render(element, document.getElementById('root'))
}

//每秒都调用 ReactDOM.render()
// setInterval(tick,1000);

//函数组件
function Welcome(props) {
    return <h1>Hello, {props.name}</h1>;
}

// class 组件 等效于上面
class Welcome1 extends React.Component {
    render() {
        return <h1>Hello, {this.props.name}</h1>;
    }
}

//组合组件
function Welcome3(props) {
    return <h1>Hello, {props.name}</h1>;
}

function App() {
    return (
        <div>
            <Welcome3 name="Sara"/>
            <Welcome3 name="Cahal"/>
            <Welcome3 name="Edite"/>
        </div>
    );
}

const element10 = <App/>

//提取组件
function Comment(props) {
    return (
        <div className="Comment">
            <div className="UserInfo">
                <img className="Avatar"
                     src={props.author.avatarUrl}
                     alt={props.author.name}
                />
                <div className="UserInfo-name">
                    {props.author.name}
                </div>
            </div>
            <div className="Comment-text">
                {props.text}
            </div>
            <div className="Comment-date">
                {formatDate(props.date)}
            </div>
        </div>
    );
}

function formatDate(date) {
    return date.toLocaleDateString();
}

const comment = {
    date: new Date(),
    text: 'I hope you enjoy learning React!',
    author: {
        name: 'Hello Kitty',
        avatarUrl: 'https://placekitten.com/g/64/64',
    },
};

function Avatar(props) {
    return (
        <img className="Avatar"
             src={props.user.avatarUrl}
             alt={props.user.name}
        />
    );
}

function Comment1(props) {
    return (
        <div className="Comment">
            <div className="UserInfo">
                <Avatar user={props.author}/>
                <div className="UserInfo-name">
                    {props.author.name}
                </div>
            </div>
            <div className="Comment-text">
                {props.text}
            </div>
            <div className="Comment-date">
                {formatDate(props.date)}
            </div>
        </div>
    );
}

function UserInfo(props) {
    return (
        <div className="UserInfo">
            <Avatar user={props.user}/>
            <div className="UserInfo-name">
                {props.user.name}
            </div>
        </div>
    );
}

const element11 = <Comment
    date={comment.date}
    text={comment.text}
    author={comment.author}
/>;

//纯函数
function sum(a, b) {
    return a + b;
}

//不是纯函数,更改了自己的入参
function withdraw(account, amount) {
    account.total -= amount;
}

//总结所有组件不能改变props,state允许react组件改变输出内容

//state
function Clock(props) {
    return (
        <div>
            <h1>Hello, world!</h1>
            <h2>It is {props.date.toLocaleTimeString()}.</h2>
        </div>
    );
}

function tick2() {
    ReactDOM.render(
        <Clock date={new Date()}/>,
        document.getElementById('root')
    );
}

// setInterval(tick2, 1000);

class Clock1 extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            date: new Date(),
        }
    }

//生命周期
    componentDidMount() {
        this.timerID = setInterval(
            () => this.tick(),
            1000
        );
    }

//生命周期清除计时器
    componentWillUnmount() {
        clearInterval(this.timerID);
    }

    tick() {
        //不要直接修改 State 比如this.state.comment = 'Hello';
        //而是应该使用 setState():
        this.setState({
            date: new Date()
        });
    }


    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
            </div>
        )
    }
}

// State 的更新可能是异步的
class AssigDemo extends React.Component {
    // Wrong
    change() {
        this.setState({
            counter: this.state.counter + this.props.increment,
        });
        // Correct 箭头函数
        this.setState((state, props) => ({
            counter: state.counter + props.increment
        }));

        // Correct 函数
        this.setState(function(state, props) {
            return {
                counter: state.counter + props.increment
            };
        });
    }
}
//State 的更新会被合并
class CombineDemo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            posts: [] ,
            comments: []
        }
    }
    componentDidMount() {

            this.setState({
                posts: response.posts

        });
            this.setState({
                comments: response.comments
            });
    }
}
// 数据是向下流动的
function FormattedDate(props) {
    return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
class Clock2 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {date: new Date()};
    }

    componentDidMount() {
        this.timerID = setInterval(
            () => this.tick(),
            1000
        );
    }

    componentWillUnmount() {
        clearInterval(this.timerID);
    }

    tick() {
        this.setState({
            date: new Date()
        });
    }

    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <FormattedDate date={this.state.date} />
            </div>
        );
    }
}

//事件
function ActionLink() {
    function handleClick(e) {
        //防止默认事件发生
        e.preventDefault();
        console.log('The link was clicked.');
    }

    return (
        <a href="#" onClick={handleClick}>
            Click me
        </a>
    );
}

class Toggle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {isToggleOn: true};

        // 为了在回调中使用 `this`，这个绑定是必不可少的
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        this.setState(state => ({
            isToggleOn: !state.isToggleOn
        }));
    }

    render() {
        return (
            <button onClick={this.handleClick}>
                {this.state.isToggleOn ? 'ON' : 'OFF'}
            </button>
        );
    }
}

//不使用 bind 的方法有两个
//1.class fields语法
class LoggingButton extends React.Component {
    // 此语法确保 `handleClick` 内的 `this` 已被绑定。
    // 注意: 这是 *实验性* 语法。
    handleClick = () => {
        console.log('this is:', "nima");
    }

    render() {
        return (
            <button onClick={this.handleClick}>
                Click me
            </button>
        );
    }
}

//2.回调箭头函数
class LoggingButton2 extends React.Component {
    handleClick() {
        console.log('this is:', this);
    }

    render() {
        // 此语法确保 `handleClick` 内的 `this` 已被绑定。
        return (
            <button onClick={() => this.handleClick()}>
                Click me
            </button>
        );
    }
}

// 向事件处理程序传递参数
class LoggingButton3 extends React.Component {
    deleteRow() {
        console.log('this is:', this);
    }


    render() {
        const id =1 ;
        // 此语法确保 `handleClick` 内的 `this` 已被绑定。
        return (
            <div>
                <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
                <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
            </div>
        );
    }
}

//条件渲染
function UserGreeting(props) {
    return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
    return <h1>Please sign up.</h1>;
}
function Greeting(props) {
    const isLoggedIn = props.isLoggedIn;
    if (isLoggedIn) {
        return <UserGreeting />;
    }
    return <GuestGreeting />;
}

//登入登出实例
function LoginButton(props) {
    return (
        <button onClick={props.onClick}>
            Login
        </button>
    );
}

function LogoutButton(props) {
    return (
        <button onClick={props.onClick}>
            Logout
        </button>
    );
}
class LoginControl extends React.Component {
    constructor(props) {
        super(props);
        this.handleLoginClick = this.handleLoginClick.bind(this);
        this.handleLogoutClick = this.handleLogoutClick.bind(this);
        this.state = {isLoggedIn: false};
    }

    handleLoginClick() {
        this.setState({isLoggedIn: true});
    }

    handleLogoutClick() {
        this.setState({isLoggedIn: false});
    }

    render() {
        const isLoggedIn = this.state.isLoggedIn;
        let button;
        if (isLoggedIn) {
            button = <LogoutButton onClick={this.handleLogoutClick} />;
        } else {
            button = <LoginButton onClick={this.handleLoginClick} />;
        }

        return (
            <div>
                <Greeting isLoggedIn={isLoggedIn} />
                {button}
            </div>
        );
    }
}

function Mailbox(props) {
    const unreadMessages = props.unreadMessages;
    return (
        <div>
            <h1>Hello!</h1>
            {unreadMessages.length > 0 &&
            <h2>
                You have {unreadMessages.length} unread messages.
            </h2>
            }
        </div>
    );
}
const messages = ['React', 'Re: React', 'Re:Re: React'];

//阻止组件渲染
function WarningBanner(props) {
    if (!props.warn) {
        return null;
    }

    return (
        <div className="warning">
            Warning!
        </div>
    );
}

class Page extends React.Component {
    constructor(props) {
        super(props);
        this.state = {showWarning: true};
        this.handleToggleClick = this.handleToggleClick.bind(this);
    }

    handleToggleClick() {
        this.setState(state => ({
            showWarning: !state.showWarning
        }));
    }

    render() {
        return (
            <div>
                <WarningBanner warn={this.state.showWarning} />
                <button onClick={this.handleToggleClick}>
                    {this.state.showWarning ? 'Hide' : 'Show'}
                </button>
            </div>
        );
    }
}

    const numbers = [1, 2, 3, 4, 5];
    const doubled = numbers.map((number) => <li>{number * 2}</li>);

function NumberList(props) {
    const numbers = props.numbers;
    const listItems = numbers.map((number) =>
        <li key={number.toString()}>
            {number}
        </li>
    );
    return (
        <ul>{listItems}</ul>
    );
}
function ListItem(props) {
    // 正确！这里不需要指定 key：
    return <li>{props.value}</li>;
}

function NumberList2(props) {
    const numbers = props.numbers;
    const listItems = numbers.map((number) =>
        // 正确！key 应该在数组的上下文中被指定
        <ListItem key={number.toString()}              value={number} />

    );
    return (
        <ul>
            {listItems}
        </ul>
    );
}




    ReactDOM.render(
        // <Game/>,
        // element,
        // getGreeting(user),
        // element3,
        // element4,
        // element5,
        // element6,
        // element7,
        // element8,
        // element9,
        // tick(),
        // <Welcome name="world"></Welcome> ,
        // <Welcome1 name="world"></Welcome1> ,
// element10 ,
//     <Comment date={comment.date} text={comment.text} author={comment.author}/>,
//     element11 ,
//     <UserInfo user={comment.author} /> ,
//     <Clock1/>,
//     <Clock2/> ,
//         <ActionLink/>,
//         <Toggle/> ,
//         <LoggingButton/>,
//         <LoggingButton3 />,
//         <Greeting isLoggedIn={true}></Greeting> ,
//         <LoginControl/> ,
//         <Mailbox  unreadMessages={messages}/> ,
//         <Page/> ,
//         <ul>{doubled}</ul> ,
//         <NumberList numbers={numbers}/> ,
        <NumberList2 numbers={numbers}/> ,
        document.getElementById('root')
    );

